#!/bin/bash
#
#	AutoFsck V3.1 by Jonathan Musther - 27th November 2007
#
#	The purpose of this script is to make checking your partitions using fsck
#	simple, streamlined and convenient.  It will prompt you on shutdown / logout
#	if any partitions need checking.
#
#	This script was written specifically for Ubuntu and derivatives, but should 
#	work on other GNU/Linux systems.  The only things to note are that this 
#	script must be run as root, and ideally should be called when the user 
#	shuts down or logs out.
#
#	If using GDM or KDE this is easily done by calling it from the script 
#	/etc/X11/gdm/PostSession/Default (in GDM), or /etc/kde3/kdm/Xreset (in KDE);
#	it will then be run when a user logs out and will have root privileges.
#
#	For all actions of this script to work correctly, move it to /usr/sbin/autofsck
#	and give execute permission to all users.
#
#	This script is released under the GNU General Public License V3 or later.
#
#
#	Check out Slingshot, a great open source game at http://www.slingshot-game.org
#
#	Contact: jmusther@gmail.com
#
#------------------SCRIPT STARTS--------------------
#
#
#This quick section simply loads the config script with GKSU.
#This way, when called from the menu, AutoFsck will be run
#as root and further prompting for the password will not be
#required.
if [ "$1" == "--menu" ]; then
	gksu "autofsck --config"
	exit
fi

function menu {
#	=================Start Menu GUI Section===================
	SELECTION=$(zenity --list --height="300" --text="Please select from the following options, and click ok:" "Disable / Enable Audible Prompt" "Set Frequency of Checks" "Check on Shutdown or on Reboot?" "Arrange Checks Now" "More Information / Help" --column="Menu:" --title="AutoFsck Configuration" --window-icon="/usr/share/pixmaps/autofsck.png")
		if [ "$?" = "1" ]; then
			exit
		fi
	case "$SELECTION" in
		"Disable / Enable Audible Prompt")
			setbeep
			menu
			exit
		;;
		"Set Frequency of Checks")
			setfreq
			menu
			exit
		;;
		"Check on Shutdown or on Reboot?")
			setreboothalt
			menu
			exit
		;;
		"Arrange Checks Now")
			testautofsck
			exit
		;;
		"More Information / Help")
			zenity --text-info --filename="/usr/share/doc/autofsck/GUI-HELP" --title="AutoFsck Help" --width="750" --height="550" --window-icon="/usr/share/pixmaps/autofsck.png"
			menu
			exit
		;;
		*)
			exit
		;;
	esac
#	=================End Menu GUI Section===================
}

function setfreq {
	#This section updates the max mount count of the filesystems
	#using tune2fs.
#	=================Start Setting Frequency=================
	#Ask the user if they want to continue:
	zenity --question --text "This will alter the frequency with which your drives are checked by AutoFsck.  Do you wish to continue?" --title="AutoFsck - Set Frequency" --window-icon="/usr/share/pixmaps/autofsck.png"
	if [ "$?" = "1" ]; then
		menu
		exit
	fi

	#If user has set the freq before, load this value from the config file:
	PREVFREQ=$(cat /etc/autofsckrc | grep "^Freq:" | cut -d" " -f2)

	#Find out how often the user wants fsck (or AutoFsck) to run:
	FREQ=$(zenity --entry --text="How often would you like to check your drives (in number of boots):" --title="AutoFsck - Set Frequency" --entry-text=$PREVFREQ --window-icon="/usr/share/pixmaps/autofsck.png") 
	if [ "$?" = "1" ]; then
		menu
		exit
	fi
	#Find the partitions we need to change:
	function mountread {
		for i in $( mount | grep --regexp="/dev/hd" --regexp="/dev/sd" ); do
			echo $i
		done
	}
	#Loop to determine filesystems that need changing, and change them.
	#MC = Mount count - MMC = Max Mount Count.
	for i in $( mountread | grep --regexp="/dev/hd" --regexp="/dev/sd" ); do
		sudo tune2fs $i -c $FREQ
	done

	#Save frequency selection to autofsckrc
	sed -i -e /Freq/d /etc/autofsckrc	#Remove old frequency line
	echo "Freq: $FREQ" >> /etc/autofsckrc	#Add current frequency line

	#Confirm:
	zenity --info --text "Your drives will now be checked after every $FREQ boots." --title="AutoFsck - Set Frequency" --window-icon="/usr/share/pixmaps/autofsck.png"
	menu
	exit
#	=================Done Setting Frequency=================
}

function setbeep {
#	=================Start Beep Change=================
	#Find out if beep is currently active.
	cat /etc/autofsckrc | grep ^beep
	if [ "$?" == "0" ]; then
		#Find out if user wants to disable it.
		zenity --question --text "AutoFsck is currently set to produce an audible alert when the question dialogue appears, would you like to turn this feature off?" --title="AutoFsck - Set Beep" --window-icon="/usr/share/pixmaps/autofsck.png"
		if [ "$?" = "0" ]; then
			#Comment out the beep line.
			sed -i -e 's/^beep/#beep/' /etc/autofsckrc
			zenity --info --text "AutoFsck's beep has been disabled." --title="AutoFsck - Set Beep" --window-icon="/usr/share/pixmaps/autofsck.png"
			menu
			exit
		fi
		menu
		exit
	fi
			cat /etc/autofsckrc | grep ^beep
			if [ "$?" == "1" ]; then
			#Find out if user wants to enable it.
			zenity --question --text "Would you like AutoFsck to produce an audible alert when the question dialogue appears?" --title="AutoFsck - Set Beep" --window-icon="/usr/share/pixmaps/autofsck.png"
			if [ "$?" = "0" ]; then
			#Uncomment out the beep line.
			sed -i -e 's/^#beep/beep/' /etc/autofsckrc
			zenity --info --text "AutoFsck's beep has been enabled." --title="AutoFsck - Set Beep" --window-icon="/usr/share/pixmaps/autofsck.png"
			menu
			exit
			fi
	fi
menu
exit
#	=================End Beep Change=================
}

function setreboothalt {
#	=================Start Shutdown/Reboot Change=================
	#Find out if check on halt is currently active.
	cat /etc/autofsckrc | grep ^halt
	if [ "$?" == "1" ]; then
		#Find out if user wants to enable it.
		zenity --question --text "AutoFsck is currently set to reboot in order to run the checks (recommended), would you like to run the check on shutdown instead?" --title="AutoFsck - Set Check Time" --window-icon="/usr/share/pixmaps/autofsck.png"
		if [ "$?" = "0" ]; then
			#Uncomment the halt line.
			sed -i -e 's/^#halt/halt/' /etc/autofsckrc
			zenity --info --text "Checks will now be run on shutdown." --title="AutoFsck - Set Check Time" --window-icon="/usr/share/pixmaps/autofsck.png"
			menu
			exit
		fi
		menu
		exit
	fi
			cat /etc/autofsckrc | grep ^halt
			if [ "$?" == "0" ]; then
			#Find out if user wants to disable it.
			zenity --question --text "AutoFsck is currently set to run the disk checks when shutting down, would you like to reboot the machine to run them instead (recommended)?" --title="AutoFsck - Set Check Time" --window-icon="/usr/share/pixmaps/autofsck.png"
			if [ "$?" = "0" ]; then
			#Comment out the halt line.
			sed -i -e 's/^halt/#halt/' /etc/autofsckrc
			zenity --info --text "In the future your machine will reboot in order to run disk checks." --title="AutoFsck - Set Check Time" --window-icon="/usr/share/pixmaps/autofsck.png"
			menu
			exit
			fi
	fi
menu
exit
#	=================End Shutdown/Reboot Change=================
}

function usage {
echo "AutoFsck v3.1 - 27th November 2007"
echo "by Jonathan Musther - jmusther@gmail.com"
echo
echo "Usage:"
echo " $0 --help      this usage information"
echo " $0 --set       easy setting of disk check frequency"
echo " $0 --beep      enable/disable the audible prompt"
echo " $0 --sr        decide whether checks are run on shutdown or reboot"
echo " $0 --config    loads the graphical configuration script"
echo " $0 --menu      as above but via gksu to get root password"
echo " $0 --check     runs the main AutoFsck script (see below)"
echo
echo "AutoFsck is a script designed to move the automatic, periodic 'just in"
echo "case' fsck - which usually runs on ext* filesystems at boot - to shutdown"
echo "To achieve this AutoFsck should be run by your display manager (GDM or KDM)"
echo "when you log out or shut down.  It then checks whether fsck is due to be"
echo "run, and that being the case, prompts the user for permission to run"
echo "the fsck on shutdown.  If the user declines, they will be prompted again"
echo "next time AutoFsck is run."
echo
echo "AutoFsck is released in the hope that it will be useful, under"
echo "the GNU General Public License version 3 or later."
echo 
echo "http://wiki.ubuntu.com/AutoFsck"
echo
exit
}

function setupfsck {
#Find out if we should beep from the config file /etc/autofsckrc
	cat /etc/autofsckrc | grep ^beep
	if [ "$?" == "0" ]; then
		beep -f 523.25 -n -f 622.25 -l 100 -n -f 698.46 -n -f 739.99 -l 100 -n -f 783.99 -n -f 932.33 -l 100 -n -f 1046.5 -l 400&
	fi
zenity --question --text "One or more of your hard disks is signalling that it is due for file system checking.\n\nIf you click 'Cancel' you will be prompted again next time you log out or shut down.\n\n'OK' to check your hard disks before your computer powers off.  This may take some time - please ensure that your computer is not running on battery power." --title="AutoFsck" --window-icon="/usr/share/pixmaps/autofsck.png"
if [ "$?" = "1" ]; then
touch /fastboot		#If user says 'no', create /fastboot and exit.
killall autofsck 	#Kill any instance of autofsck to disable the timeout.
exit
fi
#========================== Check on halt ==========================
	#If user says yes, set up for checks and then exit.
	cat /etc/autofsckrc | grep ^halt
	#Set up the check for shutdown if 'halt' specified.
	if [ "$?" == "0" ]; then
		touch /haltcheck
		rm /fastboot
		#Create script to delete /haltcheck on next boot:
		touch /tmp/rmhaltcheck.sh
			#Actually create the script
			echo \#! /bin/sh >> /tmp/rmhaltcheck.sh
			echo \# >> /tmp/rmhaltcheck.sh
			echo \# This is a temporary script, it should not be >> /tmp/rmhaltcheck.sh
			echo \# here while the system is in multi-user mode. >> /tmp/rmhaltcheck.sh
			echo \# >> /tmp/rmhaltcheck.sh
			echo rm /etc/init.d/rmhaltcheck.sh >> /tmp/rmhaltcheck.sh
			echo rm /etc/rc2.d/S*rmhaltcheck.sh >> /tmp/rmhaltcheck.sh
			echo rm /etc/rc3.d/S*rmhaltcheck.sh >> /tmp/rmhaltcheck.sh
			echo rm /etc/rc4.d/S*rmhaltcheck.sh >> /tmp/rmhaltcheck.sh
			echo rm /etc/rc5.d/S*rmhaltcheck.sh >> /tmp/rmhaltcheck.sh
			echo rm /haltcheck >> /tmp/rmhaltcheck.sh
		#Put the script in init.d and update-rc
		mv /tmp/rmhaltcheck.sh /etc/init.d/rmhaltcheck.sh
		chmod a+x /etc/init.d/rmhaltcheck.sh
		update-rc.d rmhaltcheck.sh defaults
		#Tidy up so that the script isn't run during shutdown
		#but only during the subsequent boot.
		rm /etc/rc0.d/K*rmhaltcheck.sh
		rm /etc/rc1.d/K*rmhaltcheck.sh
		rm /etc/rc2.d/K*rmhaltcheck.sh
		rm /etc/rc3.d/K*rmhaltcheck.sh
		rm /etc/rc4.d/K*rmhaltcheck.sh
		rm /etc/rc5.d/K*rmhaltcheck.sh
		rm /etc/rc6.d/K*rmhaltcheck.sh
	killall autofsck 	#Kill any instance of autofsck to disable the timeout.
	exit
	fi
#========================== Check on reboot ==========================
	#If we're not expected to check on shutdown, but rather reboot
	#create the file to force the check.
	touch /forcefsck
	rm /fastboot
	#Now create the script which will cause halt after the check:
	touch /tmp/postfsckhalt.sh
		#Actually create the script
		echo \#! /bin/sh >> /tmp/postfsckhalt.sh
		echo \# >> /tmp/postfsckhalt.sh
		echo \# This is a temporary script, it should not be >> /tmp/postfsckhalt.sh
		echo \# here while the system is in multi-user mode. >> /tmp/postfsckhalt.sh
		echo \# >> /tmp/postfsckhalt.sh
		echo rm /etc/init.d/postfsckhalt.sh >> /tmp/postfsckhalt.sh
		echo rm /etc/rc2.d/S*postfsckhalt.sh >> /tmp/postfsckhalt.sh
		echo rm /etc/rc3.d/S*postfsckhalt.sh >> /tmp/postfsckhalt.sh
		echo rm /etc/rc4.d/S*postfsckhalt.sh >> /tmp/postfsckhalt.sh
		echo rm /etc/rc5.d/S*postfsckhalt.sh >> /tmp/postfsckhalt.sh
		echo init 0 >> /tmp/postfsckhalt.sh
	#Put the script in init.d and update-rc
	mv /tmp/postfsckhalt.sh /etc/init.d/postfsckhalt.sh
	chmod a+x /etc/init.d/postfsckhalt.sh
	update-rc.d postfsckhalt.sh defaults
	#Tidy up so that the script isn't run during shutdown
	#but only during the subsequent boot.
	rm /etc/rc0.d/K*postfsckhalt.sh
	rm /etc/rc1.d/K*postfsckhalt.sh
	rm /etc/rc2.d/K*postfsckhalt.sh
	rm /etc/rc3.d/K*postfsckhalt.sh
	rm /etc/rc4.d/K*postfsckhalt.sh
	rm /etc/rc5.d/K*postfsckhalt.sh
	rm /etc/rc6.d/K*postfsckhalt.sh
	killall autofsck 	#Kill any instance of autofsck to disable the timeout.
	exit
}

function testautofsck {
#	=================Test=================
	setupfsck
	rm /fastboot
	zenity --info --text "Disk checks have now been arranged and will run when you shut down your computer." --title="AutoFsck" --window-icon="/usr/share/pixmaps/autofsck.png"
	exit
#	=================End Test=================
}

#Consolidate info about the filesystems, given by mount.
function mountread {
	for i in $( mount | grep --regexp="/dev/hd" --regexp="/dev/sd" ); do
		echo $i
	done
}

function checkcount {
#Basically this section checks the mount command for mounted 
#partitions, /dev/sdX and /dev/hdX.  Then it checks the mount count 
#and maximum mount count of each one, any which is nearly ready for 
#checking causes $CHECK to be flagged to "1" and therefore starts 
#the main user interactive bit of the script.
CHECK="0"
#Loop to determine filesystems that need checking.
#MC = Mount count - MMC = Max Mount Count.
for i in $( mountread | grep --regexp="/dev/hd" --regexp="/dev/sd" ); do
	MC=$(tune2fs -l $i | grep --regexp="Mount count:" | tr -d "Mount count:")
	MMC=$(tune2fs -l $i | grep --regexp="Maximum mount count:" | tr -d "Maximum mount count:")
	MMC=$(echo $(($MMC-1)))
if [ "$MC" -ge "$MMC" ]; then
	CHECK="1"
fi
done
#Find out if check required and prompt user.
if [ "$CHECK" = "0" ]; then #If no check required, exit.
	exit
fi				#If a check is required ask the user, then set up checks - using function setupfsck, do this in the bg:
setupfsck&
TIMEOUTKILL=$!		#Store the PID of setupfsck
#Now, in case the user doesn't see the prompt, we'll wait two minutes then tidy up, kill and exit.
sleep 120s
kill $TIMEOUTKILL	#Kill setupfsck
touch /fastboot		#Create /fastboot to make sure check is not run on next boot.
exit			#Then exit to allow shutdown to continue
}

##################### FUNCTION CALLS #####################
if [ "$1" == "--config" ]; then
	menu
	exit
fi

if [ "$1" == "--set" ]; then
	setfreq
	exit
fi

if [ "$1" == "--sr" ]; then
	setreboothalt
	exit
fi

if [ "$1" == "--check" ]; then
	checkcount
	exit
fi

usage
exit

